import base64
import hashlib

import bcrypt

from ...db import models as db
from ...db.util import transaction
from ...exceptions import MissingParameterError, \
                          MobileDuplicatedError
from ..base import BaseProcessor


def hashpw(password):
    """加密密码
    """
    hashed = bcrypt.hashpw(
        base64.b64encode(hashlib.sha256(password.encode('utf-8')).digest()),
        bcrypt.gensalt()
    )
    return hashed


def checkpw(password, hashed):
    """校验密码
    """
    return bcrypt.checkpw(password, hashed)


class UserProcessor(BaseProcessor):
    """用户基本资料/users

    Auto Generated Code.
    """
    @transaction()
    def create(self, *args, **kwargs):
        """Param

        args:( None )
        kwargs:{ ... }
        """
        # Required

        if 'mobile' not in kwargs:
            raise MissingParameterError('mobile is missing')

        if 'nickname' not in kwargs:
            raise MissingParameterError('nickname is missing')

        if 'password' not in kwargs:
            raise MissingParameterError('password is missing')

        # Unique

        if 'mobile' in kwargs:
            mobile = kwargs.get('mobile')
            if self.query(mobile=mobile, document=True):
                raise MobileDuplicatedError('mobile:{}'.format(mobile))

        if 'nickname' in kwargs:
            nickname = kwargs.get('nickname')
            if self.query(nickname=nickname, document=True):
                raise NicknameDuplicatedError('nickname:{}'.format(nickname))

        # TODO HERE
    
        # password => bcrypt => hashed
        if 'password' in kwargs:
            kwargs['password'] = hashpw(kwargs['password'])

        obj = db.User(**kwargs)
        self.dbh.add(obj)

        return obj

    @transaction()
    def read(self, *args, **kwargs):
        return self.query(*args, **kwargs)

    def query(self, *args, **kwargs):
        """Param

        args:( userID )
        kwargs:{ userid, nickname, mobile }
        """
        # 结果集
        document = kwargs.pop('document', False)
        collection = kwargs.pop('collection', False)

        # 查询参数
        params = kwargs.pop('params', {})

        q = self.dbh.query(db.User)

        if args:
            try:
                userID = args[0]
                q = q.filter_by(userid=userID)
            except IndexError:
                pass
            if collection is True:
                return q.all()
            return q.first()

        if kwargs:
            q = q.filter_by(**kwargs)
            if document is True:
                return q.first()
            return q.all()

        if document is True:
            return q.first()
        return q.all()  # collection/True

    @transaction()
    def update(self, *args, **kwargs):
        """Param

        args:( userID )
        kwargs:{ ... }
        """
        if not args or not kwargs:
            raise MissingParameterError()
            return False

        # Unique

        if 'mobile' in kwargs:
            mobile = kwargs.get('mobile')
            if self.query(mobile=mobile, document=True):
                raise MobileDuplicatedError('mobile:{}'.format(mobile))

        if 'nickname' in kwargs:
            nickname = kwargs.get('nickname')
            if self.query(nickname=nickname, document=True):
                raise NicknameDuplicatedError('nickname:{}'.format(nickname))

        userID = args[0]

        # TODO HERE

        self.dbh.query(db.User)\
                .filter_by(userid=userID)\
                .update(kwargs)

        return self.query(*args)
